import { ElMessage ,dayjs} from 'element-plus'
import * as XLSX from 'xlsx'
import OSS from 'ali-oss'
import JSZip from 'jszip'
import QRCode from 'qrcode'
import { request } from '@/api/fetch'
import { getToken, getUserInfo } from '@/utils/auth'

export function formatDate(date, label = 'YYYY-MM-DD HH:mm:ss') {
  if (date) {
    return dayjs(date).format(label)
  }
  return '--'
}
// 计算两个日期相差的天数
export function getDaysDiffNow(dateStr) {
  if (dateStr) {
    const startDate = new Date(dateStr).getTime()
    const endDate = new Date().getTime()
    const diffTime = startDate - endDate

    const diffDays = Math.ceil(diffTime / (1000 * 60 * 60 * 24))
    return diffDays
  } else {
    return '--'
  }
}

export async function createZipFileByBlobList(blobObjList) {
  const zip = new JSZip()
  const folder = zip.folder(getTodayStr())
  blobObjList.forEach((blobObj, index) => {
    folder.file(blobObj.name, blobObj.blob, { Blob: true })
  })
  let zipBlobFile = await zip.generateAsync({ type: 'blob' })
  return zipBlobFile
}
export async function createZipFileByImgList(imgList) {
  const zip = new JSZip()
  const folder = zip.folder(getTodayStr())
  imgList.forEach((imgObj) => {
    console.log('imgObj:', imgObj)
    let base64Url = imgObj.url.replace(/^data:image\/[a-z]+;base64,/, '')
    folder.file(imgObj.name, base64Url, { base64: true })
  })
  let zipBlobFile = await zip.generateAsync({ type: 'blob' })
  return zipBlobFile
}
export function randomNum(min, max) {
  if (max - min >= 1) {
    const diff = max - min
    return Math.floor(Math.random() * diff) + min
  }
  return 'min必须小于max'
}

// 生成随机字符串，字符串中既有字母也有数字
export function randomStr(length) {
  // 从第2位开始截取
  let endNum = 10
  if (length) {
    endNum = 2 + length
  }
  return Math.random().toString(36).slice(2, endNum)
}
// 生成只有字母的随机字符串
export function randomChar(length = 6) {
  // 从第2位定位
  let arr = [
    'A',
    'B',
    'C',
    'D',
    'E',
    'F',
    'G',
    'H',
    'I',
    'J',
    'K',
    'L',
    'M',
    'N',
    'O',
    'P',
    'Q',
    'R',
    'S',
    'T',
    'U',
    'V',
    'W',
    'X',
    'Y',
    'Z',
    'a',
    'b',
    'c',
    'd',
    'e',
    'f',
    'g',
    'h',
    'i',
    'j',
    'k',
    'l',
    'm',
    'n',
    'o',
    'p',
    'q',
    'r',
    's',
    't',
    'u',
    'v',
    'w',
    'x',
    'y',
    'z'
  ]
  let idvalue = ''

  for (let i = 0; i < length; i++) {
    idvalue += arr[Math.floor(Math.random() * 52)]
  }
  return idvalue
}

// 生成唯一订单号
export function tradeNo() {
  const now = new Date()
  const year = now.getFullYear()
  let month = now.getMonth() + 1
  let day = now.getDate()
  let hour = now.getHours()
  let minutes = now.getMinutes()
  let seconds = now.getSeconds()
  String(month).length < 2 ? (month = Number('0' + month)) : month
  String(day).length < 2 ? (day = Number('0' + day)) : day
  String(hour).length < 2 ? (hour = Number('0' + hour)) : hour
  String(minutes).length < 2 ? (minutes = Number('0' + minutes)) : minutes
  String(seconds).length < 2 ? (seconds = Number('0' + seconds)) : seconds
  const yyyyMMddHHmmss = `${year}${month}${day}${hour}${minutes}${seconds}`
  return yyyyMMddHHmmss + '_' + Math.random().toString(36).substr(2, 9)
}

// 显示信息
export function MyMessage(msgObj) {
  ElMessage.closeAll()
  ElMessage(msgObj)
}

// 下载有关函数
// 将表格sheet数据转成blob地址

export async function sheet2blobUrl(sheet, fileName) {
  let sheetName = 'sheet'
  var workbook = {
    SheetNames: [sheetName],
    Sheets: {}
  }
  workbook.Sheets[sheetName] = sheet
  // 生成excel的配置项
  var wopts = {
    bookType: 'xlsx', // 要生成的文件类型
    bookSST: false, // 是否生成Shared String Table，官方解释是，如果开启生成速度会下降，但在低版本IOS设备上有更好的兼容性
    type: 'binary'
  }
  var wbout = XLSX.write(workbook, wopts)
  var blob = new Blob([s2ab(wbout)], {
    type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
  })
  // 字符串转ArrayBuffer
  function s2ab(s) {
    var buf = new ArrayBuffer(s.length)
    var view = new Uint8Array(buf)
    for (var i = 0; i != s.length; ++i) view[i] = s.charCodeAt(i) & 0xff
    return buf
  }
  let url = URL.createObjectURL(blob)
  if (isMobile()) {
    console.log('fileName:', fileName)
    url = await ossUpload(fileName, blob)
  }
  // console.log('url:', url)
  return url
}

// 下载文件
export async function downFile(fileName, blob) {
  let url = URL.createObjectURL(blob)
  if (isMobile()) {
    url = await ossUpload(fileName, blob)
  }
  const el = document.createElement('a')
  el.style.display = 'none'
  // el.setAttribute('target', '_blank')

  el.href = url
  el.download = fileName
  document.body.appendChild(el)
  el.click()
  document.body.removeChild(el)
  window.URL.revokeObjectURL(url)
}

// 下载数据
export async function startDownLoadDataFn(workSheet, fileName) {
  const url = await sheet2blobUrl(workSheet, fileName)
  // console.log('download url:', url)
  downFile(url, fileName)
}

// xlsxData 二维数组
/**
 * xlsxData [[姓名,电话],['aa','13288214456']]
 * @param {*} xlsxData
 */
export function downLoadExcelFile(xlsxData, downloadFileName) {
  // 这个不能放下面，否则显示不出来数据
  let worksheet = XLSX.utils.aoa_to_sheet(xlsxData)
  let nowStr = getNowStr()
  downloadFileName = downloadFileName + '_' + nowStr + '.xlsx'
  startDownLoadDataFn(worksheet, downloadFileName)
}

export function strToBlob(str, mimeType) {
  let blob = new Blob([str], {
    type: mimeType + ';charset=utf-8'
  })
  return blob
}
export function blobToFileUrl(blob) {
  let fileUrl = URL.createObjectURL(blob)
  return fileUrl
}

export function isMobile() {
  let flag =
    /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(
      navigator.userAgent
    )
  return flag
}

export function getShortTodayStr() {
  let date = new Date()
  let year = date.getFullYear()
  let month = date.getMonth() + 1
  let day = date.getDate()

  if (month < 10) {
    month = '0' + month
  }

  if (day < 10) {
    day = '0' + day
  }

  return '' + year + month + day
}

export function getTodayStr() {
  let date = new Date()
  let year = date.getFullYear()
  let month = date.getMonth() + 1
  let day = date.getDate()
  let hour = date.getHours()
  let minute = date.getMinutes()
  let second = date.getSeconds()
  if (month < 10) {
    month = '0' + month
  }

  if (day < 10) {
    day = '0' + day
  }
  if (hour < 10) {
    hour = '0' + hour
  }
  if (minute < 10) {
    minute = '0' + minute
  }
  return '' + year + month + day
}

export function getNowStr() {
  let date = new Date()
  let year = date.getFullYear()
  let month = date.getMonth() + 1
  let day = date.getDate()

  return (
    String(year) +
    String(month) +
    String(day) +
    String(date.getMinutes()) +
    String(date.getSeconds())
  )
}
function getRoomUnit() {
  const num = randomNum(0, 3)
  if (num === 0) {
    return '号'
  } else if (num === 1) {
    return '室'
  } else if (num === 2) {
    return ''
  }
  return ''
}

export function numToString(num, beLength = 2) {
  if (beLength === 2) {
    if (num >= 0 && num < 10) {
      return '0' + num
    }
    return String(num)
  } else if (beLength === 3) {
    if (num >= 0 && num < 10) {
      return '00' + num
    } else if (num >= 10 && num < 100) {
      return '0' + num
    }
    return String(num)
  } else if (beLength === 4) {
    if (num >= 0 && num < 10) {
      return '000' + num
    } else if (num >= 10 && num < 100) {
      return '00' + num
    } else if (num >= 100 && num < 1000) {
      return '0' + num
    }
    return String(num)
  } else if (beLength === 5) {
    if (num >= 0 && num < 10) {
      return '0000' + num
    } else if (num >= 10 && num < 100) {
      return '000' + num
    } else if (num >= 100 && num < 1000) {
      return '00' + num
    } else if (num >= 1000 && num < 10000) {
      return '0' + num
    }
    return String(num)
  } else if (beLength === 6) {
    if (num >= 0 && num < 10) {
      return '00000' + num
    } else if (num >= 10 && num < 100) {
      return '0000' + num
    } else if (num >= 100 && num < 1000) {
      return '000' + num
    } else if (num >= 1000 && num < 10000) {
      return '00' + num
    } else if (num >= 10000 && num < 100000) {
      return '0' + num
    }
    return String(num)
  } else if (beLength === 7) {
    if (num >= 0 && num < 10) {
      return '000000' + num
    } else if (num >= 10 && num < 100) {
      return '00000' + num
    } else if (num >= 100 && num < 1000) {
      return '0000' + num
    } else if (num >= 1000 && num < 10000) {
      return '000' + num
    } else if (num >= 10000 && num < 100000) {
      return '00' + num
    } else if (num >= 100000 && num < 1000000) {
      return '0' + num
    }
    return String(num)
  }
  return String(num)
}

// 判断是不是微信

export function needOuterBrowser() {
  let ua = navigator.userAgent
  if (/micromessenger|Alipay/i.test(ua) && isMobile()) {
    // 微信
    return true
  }
  return false
}

// 转译regexp的特殊符号，如果不转译调用xlsx的sheet_to_csv方法会报错* . ? + ^ $ |  / [ ] ( ) { }

export function escapeRegExp(string) {
  return string.replace(/[.*+?^${}()|[\]]/g, '\\$&')
  //$&表示整个被匹配的字符串
}

export function getSpecialCharOriginChar(str) {
  // \r \n \t 等符号是
  return str
    .replaceAll('\\r', '\r')
    .replaceAll('\\n', '\n')
    .replaceAll('\\t', '\t')
}

export function arrayBufferToString(buffer) {
  return String.fromCharCode.apply(null, new Uint8Array(buffer))
}

export const rowBreakReg = /\r?\n/g

// columnBreakReg [\t\s,，；;|]后不要加+号，否则有空单元格的话列错位
export const columnBreakReg = /[\t\s,，；;|](?=(?:[^"]*"[^"]*")*[^"]*$)/g

export async function readTxtFile(file) {
  return new Promise((resolve, reject) => {
    const reader = new FileReader()
    reader.readAsText(file, 'utf-8')
    reader.onload = (e) => {
      const txtString = e.target.result
      // utf-8 的 中文编码 正则表达式
      const patrn = /[\u4E00-\u9FA5]/gi
      // 检测当前文本是否含有中文（如果没有，则当乱码处理）
      // 两个格式的英文编码一样，所以纯英文文件也当成乱码再处理一次
      if (!patrn.exec(txtString)) {
        let reader_gb2312 = new FileReader()
        // 再拿一次纯文本，这一次拿到的文本一定不会乱码
        reader_gb2312.readAsText(file, 'gb2312')
        reader_gb2312.onload = (e2) => {
          resolve(e2.target.result)
        }
      } else {
        resolve(txtString)
      }
    }
  })
}

async function createImage(qrUrl, width, height) {
  return new Promise((resolve) => {
    let imgEle = new Image(width, height)
    imgEle.src = qrUrl
    imgEle.onload = function () {
      resolve(imgEle)
    }
  })
}
/**
 * 二维码生成
 * @param content 生成二维码内容
 * @param desc 二维码底部描述
 * @param qrcodeDom 挂在dom
 * @returns {*|HTMLDivElement}
 */
export async function generatorQrcode(content, desc = '') {
  let qrWidth = 256
  let textLineHeight = 30 // 文字的行高
  let fontSize = 28 // 文字大小
  let qrMargin = 10 // 描述文字距离边框的距离

  // 将文本内容生成图片
  let qrUrl = await QRCode.toDataURL(content, {
    width: qrWidth,
    errorCorrectionLevel: 'H',
    type: 'image/png',
    margin: 1
  })
  // qrUrl为base64
  // return qrUrl
  let imgEle = await createImage(qrUrl, qrWidth, qrWidth)

  // 将图片画到二维码上
  let canvas = document.createElement('canvas')
  let canvasWidth = qrWidth + qrMargin * 2

  canvas.width = canvasWidth
  let ctx = canvas.getContext('2d')
  // 描述文字在canvas上能够画几行
  ctx.font = fontSize + 'px serif'
  let canvasTxtRowList = getCanvasTextRow(ctx, desc, qrWidth)
  // console.log('canvasTxtRowList:',canvasTxtRowList)

  let canvasHeight =
    qrWidth + qrMargin * 2 + textLineHeight * canvasTxtRowList.length + qrMargin
  // 计算canvas的高度
  canvas.height = canvasHeight

  // 绘制背景
  ctx.fillStyle = 'rgb(255,255,255)'

  // console.log('canvasWidth:',canvasWidth)
  // console.log('canvasHeight:',canvasHeight)
  ctx.fillRect(0, 0, canvasWidth, canvasHeight)
  // 画图
  ctx.drawImage(imgEle, qrMargin, qrMargin, qrWidth, qrWidth) // 填充二维码
  // 填充背景

  // 填充文字
  ctx.fillStyle = 'rgb(0,0,0)' // 调色(纯黑)
  ctx.font = fontSize + 'px serif'
  ctx.textAlign = 'center'
  ctx.textBaseline = 'top'
  //处理文字描述,太长换行问题
  // let fontStartTop = qrWidth + qrMargin * 2
  for (let b = 0; b < canvasTxtRowList.length; b++) {
    ctx.fillText(
      canvasTxtRowList[b],
      canvasWidth / 2,
      canvasWidth + b * textLineHeight
    ) // 每行字体y坐标间隔20
  }
  // console.log('canvas.toDataURL')
  return canvas.toDataURL()
}

//
function getCanvasTextRow(ctx, desc, width) {
  let temp = ''
  const row = []
  for (let a = 0; a < desc.length; a++) {
    if (
      ctx.measureText(temp).width < width &&
      ctx.measureText(temp + desc[a]).width <= width
    ) {
      temp += desc[a]
    } else {
      row.push(temp)
      temp = desc[a]
    }
  }
  if (temp) {
    row.push(temp)
  }

  return row
}
export function base64ToBlob(base64, mimeType) {
  // 解码Base64字符串
  const byteCharacters = window.atob(base64)
  // 创建一个8位无符号整数值的数组，长度等于解码后的字符串长度
  const byteNumbers = new Array(byteCharacters.length)
  for (let i = 0; i < byteCharacters.length; i++) {
    byteNumbers[i] = byteCharacters.charCodeAt(i)
  }
  // 将整数数组转换为Uint8Array
  const byteArray = new Uint8Array(byteNumbers)
  // 使用Uint8Array创建Blob对象
  return new Blob([byteArray], { type: mimeType })
}
export function sanitizeFileName(fileName) {
  // 正则表达式匹配Windows文件名中不允许的字符
  var invalidChars = /[<>:"\/\\|?*]/g
  // 将匹配到的字符替换为空字符串
  var sanitizedFileName = fileName.replace(invalidChars, '')
  return sanitizedFileName.slice(0, 30)
}

export function randomFileName(ext = '.txt') {
  const randomString =
    Date.now().toString(36) + Math.random().toString(36).substring(2)
  return randomString + ext
}

export function getPureFileName(fileName) {
  return fileName.replace(/\.[^/.]+$/, '')
}

// 将数组按个数拆分成多个数组
export function chunkArray(array, size) {
  const result = []
  for (let i = 0; i < array.length; i += size) {
    result.push(array.slice(i, i + size))
  }
  return result
}

export async function initOss() {
  let credentials = await request('/public/getOssTempSTS', {
    method: 'POST'
  })
  console.log('credentials:', credentials)
  const client = new OSS({
    // yourRegion填写Bucket所在地域。以华东1（杭州）为例，Region填写为oss-cn-hangzhou。
    region: 'oss-cn-beijing',
    accessKeyId: credentials.AccessKeyId,
    accessKeySecret: credentials.AccessKeySecret,
    stsToken: credentials.SecurityToken,
    Expiration: credentials.Expiration,
    // 填写Bucket名称。
    bucket: 'gg-prize',
    refreshSTSToken: async () => {
      const credentials = await request('/public/getOssTempSTS', {
        method: 'POST'
      })
      return {
        accessKeyId: credentials.AccessKeyId,
        accessKeySecret: credentials.AccessKeySecret,
        stsToken: credentials.SecurityToken
      }
    }
  })
  // console.log('client:', client)
  return client
}

export async function ossUpload(fileName, blobData) {
  const client = await initOss()
  return new Promise((resolve, reject) => {
    client
      .put(fileName, blobData)
      .then((res) => {
        // console.log("res:", res);
        if (res.res.status === 200) {
          resolve(res.url)
        } else {
          reject(null)
        }
      })
      .catch((err) => {
        reject(err)
      })
  })
}

export function isLogin() {
  const token = getToken()
  const userInfo = getUserInfo()
  // console.log('token:',token)
  // console.log('userInfo:',userInfo)
  // 当token存在，用户信息存在且用户信息中有手机号，则认为用户已经登录成功
  if (
    token &&
    userInfo &&
    (userInfo.role === 'vip' || userInfo.role === 'admin')
  ) {
    return true
  } else {
    return false
  }
}

// 将对象按键值从大到小排序后，转成数组
/**
 * obj 格式：{a:1,b:2,c:3}  a出现1次 b出现2次 c出现3次
 * result 格式：[{num:1,valueList:['a'],valueStr:'a'},{num:2,valueList:['b'],valueStr:'b'},{num:3,valueList:['c'],valueStr:'c'}]
 * @param {*} obj
 * @returns
 */
export function keyNumObjToArray(obj) {
  let tempNumObj = {}
  for (let key in obj) {
    let num = obj[key]
    if (tempNumObj[num]) {
      tempNumObj[num].push(key)
    } else {
      tempNumObj[num] = [key]
    }
  }
  let tempResultKeys = Object.keys(tempNumObj).sort((a, b) => b - a)
  let result = []
  tempResultKeys.forEach((num) => {
    let valueList = tempNumObj[num]
    // 按数值从小到大排列
    valueList.sort((a, b) => Number(a) - Number(b))
    result.push({
      num,
      valueList: valueList,
      valueStr: valueList.join('，')
    })
  })
  return result
}
// 将汉字num转成数字num

export function chineseNumToNumber(chineseNumber) {
  if (/[一二两俩三四五六七八九十百]/.test(chineseNumber)) {
    const digitMap = {
      零: 0,
      一: 1,
      两: 2,
      俩: 2,
      二: 2,
      三: 3,
      四: 4,
      五: 5,
      六: 6,
      七: 7,
      八: 8,
      九: 9
    }
    const unitMap = {
      十: 10,
      百: 100,
      千: 1000,
      万: 10000
    }
    let result = 0
    let temp = 0
    for (let i = 0; i < chineseNumber.length; i++) {
      const char = chineseNumber[i]
      if (digitMap[char] !== undefined) {
        temp = digitMap[char]
      } else if (unitMap[char] !== undefined) {
        if (unitMap[char] === 10 && temp === 0) {
          temp = 1
        }
        result += temp * unitMap[char]
        temp = 0
      }
    }
    result += temp
    return result
  } else {
    return chineseNumber
  }
}
export function deepCopy(target) {
  if (typeof target !== 'object' || target === null) {
      return target;
  }

  let result;
  if (Array.isArray(target)) {
      result = [];
      for (let i = 0; i < target.length; i++) {
          result[i] = deepCopy(target[i]);
      }
  } else {
      result = {};
      for (let key in target) {
          if (target.hasOwnProperty(key)) {
              result[key] = deepCopy(target[key]);
          }
      }
  }
  return result;
}